fix #2125: duplicate binary names will cause a bail
authorpsyomn <lethaljellybean@gmail.com>
Mon, 23 Nov 2015 00:47:30 +0000 (19:47 -0500)
committerpsyomn <lethaljellybean@gmail.com>
Tue, 8 Dec 2015 17:15:41 +0000 (12:15 -0500)
* adds duplicate target checks for bins, tests, examples, benches
* adds tests to test the above

src/cargo/util/toml.rs
tests/test_bad_config.rs

index 48df6031b7b8fefcfa76b60efce4061b2ec98b39..e7e910b3c79bf0f243d8245d5beb7bd5e34ce3b3 100644 (file)
@@ -1,4 +1,4 @@
-use std::collections::HashMap;
+use std::collections::{HashMap, HashSet};
 use std::default::Default;
 use std::fmt;
 use std::fs;
@@ -465,6 +465,26 @@ impl TomlManifest {
             None => inferred_bench_targets(layout)
         };
 
+        if let Err(e) = unique_names_in_targets(&bins) {
+            bail!("found duplicate binary name {}, but all binary targets \
+                   must have a unique name", e);
+        }
+
+        if let Err(e) = unique_names_in_targets(&examples) {
+            bail!("found duplicate example name {}, but all binary targets \
+                   must have a unique name", e);
+        }
+
+        if let Err(e) = unique_names_in_targets(&benches) {
+            bail!("found duplicate bench name {}, but all binary targets must \
+                   have a unique name", e);
+        }
+
+        if let Err(e) = unique_names_in_targets(&tests) {
+            bail!("found duplicate test name {}, but all binary targets must \
+                   have a unique name", e)
+        }
+
         // processing the custom build script
         let new_build = project.build.as_ref().map(PathBuf::from);
 
@@ -561,6 +581,19 @@ impl TomlManifest {
     }
 }
 
+/// Will check a list of toml targets, and make sure the target names are unique within a vector.
+/// If not, the name of the offending binary target is returned.
+fn unique_names_in_targets(targets: &[TomlTarget]) -> Result<(), String> {
+    let values = targets.iter().map(|e| e.name()).collect::<Vec<String>>();
+    let mut seen = HashSet::new();
+    for v in values {
+        if !seen.insert(v.clone()) {
+            return Err(v);
+        }
+    }
+    Ok(())
+}
+
 fn validate_library_name(target: &TomlTarget) -> CargoResult<()> {
     match target.name {
         Some(ref name) => {
index cbf84d15ccdfb617e88ded9636aed4a485e2a809..e1d85ef71e57431406c5ab09d6a356b73f030720 100644 (file)
@@ -284,3 +284,87 @@ Cargo.toml:[..]
 
 "));
 });
+
+test!(duplicate_binary_names {
+    let foo = project("foo")
+    .file("Cargo.toml", r#"
+       [package]
+       name = "qqq"
+       version = "0.1.0"
+       authors = ["A <a@a.a>"]
+
+       [[bin]]
+       name = "e"
+       path = "a.rs"
+
+       [[bin]]
+       name = "e"
+       path = "b.rs"
+    "#)
+    .file("a.rs", r#"fn main() -> () {}"#)
+    .file("b.rs", r#"fn main() -> () {}"#);
+
+    assert_that(foo.cargo_process("build"),
+                execs().with_status(101).with_stderr("\
+failed to parse manifest at `[..]`
+
+Caused by:
+  found duplicate binary name e, but all binary targets must have a unique name
+"));
+});
+
+test!(duplicate_example_names {
+    let foo = project("foo")
+    .file("Cargo.toml", r#"
+       [package]
+       name = "qqq"
+       version = "0.1.0"
+       authors = ["A <a@a.a>"]
+
+       [[example]]
+       name = "ex"
+       path = "examples/ex.rs"
+
+       [[example]]
+       name = "ex"
+       path = "examples/ex2.rs"
+    "#)
+    .file("examples/ex.rs", r#"fn main () -> () {}"#)
+    .file("examples/ex2.rs", r#"fn main () -> () {}"#);
+
+    assert_that(foo.cargo_process("build").arg("--example").arg("ex"),
+                execs().with_status(101).with_stderr("\
+failed to parse manifest at `[..]`
+
+Caused by:
+  found duplicate example name ex, but all binary targets must have a unique name
+"));
+});
+
+test!(duplicate_bench_names {
+    let foo = project("foo")
+    .file("Cargo.toml", r#"
+       [package]
+       name = "qqq"
+       version = "0.1.0"
+       authors = ["A <a@a.a>"]
+
+       [[bench]]
+       name = "ex"
+       path = "benches/ex.rs"
+
+       [[bench]]
+       name = "ex"
+       path = "benches/ex2.rs"
+    "#)
+    .file("benches/ex.rs", r#"fn main () {}"#)
+    .file("benches/ex2.rs", r#"fn main () {}"#);
+
+    assert_that(foo.cargo_process("bench"),
+                execs().with_status(101).with_stderr("\
+failed to parse manifest at `[..]`
+
+Caused by:
+  found duplicate bench name ex, but all binary targets must have a unique name
+"));
+});